package com.example.demo.mock;

import com.alibaba.fastjson.JSON;
import com.dhcc.csmsearch.common.model.Const;
import com.dhcc.csmsearch.elasticsearch.common.ElasticsearchManage;
import com.example.demo.jobs.hbase.LisSynTest;
import com.sun.org.apache.bcel.internal.generic.DADD;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.ScriptSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.ExecutionException;

public class MockUtil {
    private static Logger logger = LoggerFactory.getLogger(MockUtil.class);

    private final static String ENV_DEV = "dev";

    private String Env;

    private Boolean isDev = false;

    private int total;

    private ElasticsearchManage elasticManage;

    public MockUtil(String env, int total) {
        this.Env = env;
        this.total = total;

        if (env.equals(ENV_DEV)) {
            isDev = true;
        }
    }

    public MockUtil(String env, int total, ElasticsearchManage elasticManage) {
        this.Env = env;
        this.total = total;

        if(this.total > 5000){
            this.total = 5000;
        }
        this.elasticManage = elasticManage;
        if (env.equals(ENV_DEV)) {
            isDev = true;
        }
    }

    public void setElasticManage(ElasticsearchManage elasticManage) {
        this.elasticManage = elasticManage;
    }

    public List<Map<String, Object>> buildPatientData() {
        return buildPatientData(null);
    }

    public List<Map<String, Object>> buildPatientData(MockData data) {

        List<Map<String, Object>> maps = new ArrayList<>();
        String[] sexCode = {"0", "1", "2", "9"};
        String[] nationCode = {"01", "02", "03", "04", "04"};
        String[] maritalCode = {"1", "2", "9", "3", "4"};
        String[] birthday = {"", null, "2018-01-01", "2018-10-3 11:11:00", "2018-01-01 11:11:00.0"};
        for (int i = 0; i < total; i++) {
            Map<String, Object> object = new HashMap<>();

            if (data != null) {
                object.put("routing", data.getRegno());
                object.put("pat_regno", data.getRegno());
            } else {
                object.put("routing", "1234" + i);
                object.put("pat_regno", "1234" + i);

            }
            object.put("pat_recordno", "12314" + i);
            object.put("pat_name", getName());
            object.put("pat_idcard", "141122199309090101" + i);
            if (!isDev) {
                object.put("pat_gender_code", getRandom(sexCode));
                object.put("pat_nation_code", null);
                object.put("pat_marital_code", getRandom(maritalCode));
            }

            object.put("pat_birthday", getRandom(birthday));

            maps.add(object);
        }

        return maps;
    }

    public List<Map<String, Object>> buildAdmData() {
        return buildAdmData(null);
    }

    public List<Map<String, Object>> buildAdmData(List<MockData> data) {
        List<Map<String, Object>> maps = new ArrayList<>();

        for (int i = 0; i < total; i++) {
            Map<String, Object> object = getAdm(data);
            maps.add(object);
        }

        return maps;
    }

    public List<Map<String, Object>> buildDiagnoseData() {
        return buildDiagnoseData(null);
    }

    public List<Map<String, Object>> buildDiagnoseData(List<MockData> data) {
        List<Map<String, Object>> maps = new ArrayList<>();


        for (int i = 0; i < total; i++) {
            Map<String, Object> object = getDiagnose(data);

            maps.add(object);
        }

        return maps;
    }

    public List<Map<String, Object>> buildOrdItemData() {
        return buildOrdItemData(null);
    }
    public List<Map<String, Object>> buildOrdItemData(List<MockData> data) {

        List<Map<String, Object>> maps = new ArrayList<>();

        for (int i = 0; i < total; i++) {
            Map<String, Object> object = getOrdItem(data);

            maps.add(object);
        }

        return maps;
    }

    public List<Map<String, Object>> buildLisitemData(){
        return buildLisitemData(null);
    }

    public List<Map<String, Object>> buildLisitemData(List<MockData> data) {

        List<Map<String, Object>> maps = new ArrayList<>();

        for (int i = 0; i < total; i++) {
            Map<String, Object> object = getLisItem(data);

            maps.add(object);
        }

        return maps;
    }
    public List<Map<String, Object>> buildOrdRisData() {
        return buildOrdRisData(null);
    }
    public List<Map<String, Object>> buildOrdRisData(List<MockData> data) {

        List<Map<String, Object>> maps = new ArrayList<>();

        for (int i = 0; i < total; i++) {
            Map<String, Object> object = getOrdRis(data);

            maps.add(object);
        }

        return maps;
    }

    private Map<String, Object> getAdm(List<MockData> data) {
        String[] birthday = {"1990-01-02", "1980-01-02", "1995-11-02", ""};
        String[] hospitalCode = {"HXEY", "1001", "1002"};
        String[] admType = {"O", "E", "I", "H", ""};
        String[] admState = {"A", "C", "D", "P", ""};
        String[] deptCode = {"03071074-IP07400-HX07401B", "03071074-IP07400-HX07403G",
                "03071075-IP07500-HX07501B", "03071075-IP07500-JJ07503G"};

        Map<String, Object> object = new HashMap<>();

        if (data != null) {
            MockData curData = data.get(new Random().nextInt(data.size()));
            object.put("mr_admid", curData.getAdmno());
            object.put("mr_regno", curData.getRegno());
        } else {
            object.put("mr_admid", "1234");
            object.put("mr_regno", "12314");
        }

        object.put("mr_admdate", "2010-01-01 00:00:00");
        object.put("mr_admtime", "10:20:20");
        object.put("mr_dischdate", "2010-11-01 00:0:00");
        object.put("mr_dischtime", "10:20:20");

        object.put("mr_admhospital_code", getRandom(hospitalCode));
        object.put("mr_admtype_code", getRandom(admType));
        object.put("mr_admdept_code", getRandom(deptCode));
        object.put("mr_dischdept_code", getRandom(deptCode));
        object.put("mr_visitstatus_code", getRandom(admState));
        object.put("mr_birthday", getRandom(birthday));
        return object;
    }

    private Map<String, Object> getDiagnose(List<MockData> data) {
        String[] diagtype = {"M", "PRE"};
        String[] diagnose = {"1", "2", "3", "", "", ""};
        String[] diagnoseName = {"上感", "支气管炎", "哮喘 AR", "外阴瘙痒", "宫颈癌", "急性咽炎", "肺炎",  "子宫内膜癌"};
        Map<String, Object> object = new HashMap<>();

        object.put("diag_id", MathUtils.getUUID());
        if (data != null) {
            MockData curData = data.get(new Random().nextInt(data.size()));
            object.put("routing", curData.getRegno());
            object.put("diag_admid", curData.getAdmno());
            object.put("diag_regno", curData.getRegno());
        } else {
            String regNo = MathUtils.getRegNo();
            String admNo = MathUtils.getAdmNo();
            object.put("routing", regNo);
            object.put("diag_admid", admNo);
            object.put("diag_regno", regNo);
        }

        object.put("diag_date", "2019-01-01 00:00:00");
        object.put("diag_time", "11:01:01");
        object.put("diag_type_code", getRandom(diagtype));
        object.put("diag_code", getRandom(diagnose));
        object.put("diag_name", getRandom(diagnoseName));

        return object;
    }

    private Map<String, Object> getOrdItem(List<MockData> data) {
        String[] ordName = {"JZ015", "010101011400001", "JC0271",
                "11020000118", "JY819", "010702020000001", "JY820","110200001", "JY0232", "JY0232", "0211013001",
                "011402010000004", "0201021001"};
        String[] ord_type = {"S", "OUT", "NORM"};
        String[] ord_status = {"V", "U", "H", "D", "P"};
        String[] ord_cate = {"01", "02", "03", "04"};
        String[] freq_code = {"Tid", "Bid", "Qd", "Qid"};
        String[] ord_duration_code = {"1", "2", "3", "4"};

        String[] deptCode = {"03071074-IP07400-HX07401B", "03071074-IP07400-HX07403G",
                "03071075-IP07500-HX07501B", "03071075-IP07500-JJ07503G"};
        String[] ord_usage = {"口服", "含服", "静脉注射", ""};

        Map<String, Object> object = new HashMap<>();
        object.put("ord_id", MathUtils.getUUID());
        if(data != null){
            MockData curData = data.get(new Random().nextInt(data.size()));
            object.put("ord_admno", curData.getAdmno());
            object.put("ord_regno", curData.getRegno());
        }else {
            String regNo = MathUtils.getRegNo();
            String admNo = MathUtils.getAdmNo();
            object.put("ord_admno", regNo);
            object.put("ord_regno", admNo);
        }

        object.put("ord_startdate", "2010-01-01 00:00:00");
        object.put("ord_starttime", "10:20:60");
        object.put("ord_enddate", "2010-11-01 00:00:00");
        object.put("ord_endtime", "10:21:60");
        object.put("ord_doseqty", "1");
        object.put("ord_code", getRandom(ordName));
        object.put("ord_type_code", getRandom(ord_type));
        object.put("ord_status_code", getRandom(ord_status));
        object.put("ord_cate_code", getRandom(ord_cate));
        object.put("ord_freq_code", getRandom(freq_code));
        object.put("ord_duration_code", getRandom(ord_duration_code));
        object.put("ord_dept_code", getRandom(deptCode));
        object.put("ord_execdept_code", getRandom(deptCode));
        object.put("ord_usage_code", getRandom(ord_usage));

        return object;
    }

    private Map<String, Object> getOrdRis(List<MockData> data){
        String[] ordName = {"JC0004", "JC0255", "JC0004",
                "JC0090", "270200004", "JC0212"};

        String[] ordDesc = {
                "<宫颈涂片>取样满意。鳞状上皮细胞炎症反应性改变，建议随访或复查。",
                "静息状态： 尿道内口关闭，膀胱容量14ml（＜50ml）；膀胱逼尿肌厚度0.2cm（＜0.5cm）；膀胱颈位于耻骨联合下缘参考线上方2.1cm，膀胱后角约127°；宫颈下缘与阴道外口距离约4.0cm。Valsalva动作： 尿道内口关闭，尿道旋转角约24°；膀胱颈位于耻骨联合下缘参考线下方0.6cm，膀胱后角约151°，宫颈下缘与阴道外口距离约4.0cm；未见直肠膨出征象。经会阴三维超声： 肛提肌走形正常，未见肛提肌断裂征象，肛提肌间隙基本对称，静息状态时肛提肌裂孔面积11.7cm2，最大Valsalva时肛提肌裂孔面积17.8cm2。肛门内、外括约肌连续。",
                "子宫前位，宫体大小3.8x4.8x4.6cm，内膜居中，厚0.35cm（单层），节育环居中，肌壁回声均匀，未探及明显异常血流信号。 右附件区查见大小5.1x3.5x4.3cm的不均质稍强回声，边界较清，未探及血流信号。 左附件区未见确切占位。"
        };

        String[] ordResult = {
                "双侧乳腺未见确切占位",
                "膀胱尿道膨出",
                "三尖瓣反流（轻度） 左室收缩功能测值正常",
                "高危型：HPV16（+）",
                "宫内早孕（双孕囊双胎芽，建议复查）",
                "宫内单活胎"
        };
        Map<String, Object> object = new HashMap<>();
        object.put("or_id", MathUtils.getUUID());
        if(data != null){
            MockData curData = data.get(new Random().nextInt(data.size()));
            object.put("or_admno", curData.getAdmno());
            object.put("or_regno", curData.getRegno());
        }else {
            object.put("or_admno", MathUtils.getAdmNo());
            object.put("or_regno", MathUtils.getRegNo());
        }

        object.put("check_date", "2018-01-01 10:12:23");

        object.put("or_ordcode", getRandom(ordName));
        object.put("or_desc", getRandom(ordDesc));
        object.put("or_result", getRandom(ordResult));
        object.put("or_name", getRandom(ordName));

        return object;
    }

    private Map<String, Object> getLisItem(List<MockData> data){
        String[] ordName = {"JZ015", "010101011400001", "11020000117",
                "11020000118", "030205010007", "010702020000001"};
        String[] lisdate = {"20180514", "20180514", "20180514",
                "20180608", "20180618", "20180617"};
        String[] listime = {"021257", "092310", "092309",
                "092310", "092310", "092317"};
        String[] lisValue = {"42.1", "4.8", "0"};

        List<Map<String, Object>> lisItems = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>();
        map1.put("name", "白细胞");
        map1.put("code", "JY0104_WBC");
        map1.put("ordName", "JY0104");
        map1.put("lis_searchcode", "JY0104_WBC");
        lisItems.add(map1);
        Map<String, Object> map2 = new HashMap<>();
        map2.put("name", "红细胞");
        map2.put("code", "JY0104_RBC");
        map2.put("ordName", "JY0104");
        map2.put("lis_searchcode", "JY0104_RBC");
        lisItems.add(map2);
        Map<String, Object> map3 = new HashMap<>();
        map3.put("name", "酮体");
        map3.put("code", "JY0104_KET");
        map3.put("ordName", "JY0104");
        map3.put("lis_searchcode", "JY0104_KET");
        lisItems.add(map3);
        Map<String, Object> map4 = new HashMap<>();
        map4.put("name", "酮体");
        map4.put("code", "JY0256_CRP");
        map4.put("ordName", "JY0256");
        map4.put("lis_searchcode", "JY0256_CRP");
        lisItems.add(map4);

        Map<String, Object> map5 = new HashMap<>();
        map5.put("name", "铜兰蛋白");
        map5.put("code", "250401028_CP");
        map5.put("ordName", "250401028");
        map5.put("lis_searchcode", "250401028_CP");
        lisItems.add(map5);


        Map<String, Object> object = new HashMap<>();
        object.put("inspection_id", "123");
        object.put("test_item_id", "a");
        object.put("lis_id", MathUtils.getUUID());
        if(data != null){
            MockData curData = data.get(new Random().nextInt(data.size()));
            object.put("lis_admno", curData.getAdmno());
            object.put("lis_regno", curData.getRegno());
        }else {
            object.put("lis_admno", MathUtils.getAdmNo());
            object.put("lis_regno", MathUtils.getRegNo());
        }

        Map<String, Object> curLis = lisItems.get(new Random().nextInt(lisItems.size()));

        object.put("lis_name", curLis.get("name"));
        object.put("lis_code", curLis.get("code"));
        object.put("lis_value", getRandom(lisValue));
        object.put("lis_result", "");
        object.put("lis_date", getRandom(lisdate));
        object.put("lis_time", getRandom(listime));
        object.put("lis_ordcode", curLis.get("ordName"));
        object.put("lis_searchcode", curLis.get("lis_searchcode"));

        return object;
    }

    private String getRandom(String[] arr) {
        int index = (int) (Math.random() * arr.length);

        return arr[index];
    }

    /**
     * 随机获取ES中的登记号和就诊号
     *
     * @return
     */
    public List<MockData> getRandomForES() throws ExecutionException, InterruptedException {
        if (this.elasticManage == null) {
            throw new NullPointerException("ElasticsearchManage is null");
        }

        Map<String, Object> params = new HashMap<>();
        Script script = new Script(ScriptType.INLINE, "painless", "Math.random()", params);
        ScriptSortBuilder scriptSortBuilder = SortBuilders.scriptSort(script, ScriptSortBuilder.ScriptSortType.NUMBER).order(SortOrder.DESC);

        TermQueryBuilder termQuery = QueryBuilders.termQuery("join_field", Const.dafault_csmsearch_medicalrecord_table);


        ScriptSortBuilder sortBuilder = new ScriptSortBuilder(script, ScriptSortBuilder.ScriptSortType.NUMBER).order(SortOrder.ASC);

        SearchResponse response = elasticManage.getTransportClient()
                .prepare().prepareSearch("csmsearch").setFrom(0).setSize(1000).addSort(sortBuilder)
                .setQuery(termQuery).execute().get();

        SearchHits hits = response.getHits();

        SearchHit[] hitArr = hits.getHits();
        List<SearchHit> hitList = new ArrayList<>();

        for (SearchHit hit : hits.getHits()) {
            hitList.add(hit);
        }
        List<MockData> mockData = new ArrayList<>();

        for (int i = 0; i < 200; i++) {
            //显示对象并将其从列表中删除,从而实现不重复.
            SearchHit hit = hitList.remove(new Random().nextInt(hitList.size()));
            Map<String, Object> map = hit.getSourceAsMap();

            String regno = map.getOrDefault("regno", "").toString();
            String admno = map.getOrDefault("admno", "").toString();

            if (!StringUtils.isEmpty(regno) && !StringUtils.isEmpty(admno)) {
                MockData data = new MockData();
                data.setRegno(regno);
                data.setAdmno(admno);
                mockData.add(data);

                if (mockData.size() > 100) {
                    break;
                }
            }
        }

        return mockData;
    }

    private String getName() {
        Random random = new Random();
        String[] Surname = {"赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋", "沈", "韩", "杨", "朱", "秦", "尤", "许",
                "何", "吕", "施", "张", "孔", "曹", "严", "华", "金", "魏", "陶", "姜", "戚", "谢", "邹", "喻", "柏", "水", "窦", "章", "云", "苏", "潘", "葛", "奚", "范", "彭", "郎",
                "鲁", "韦", "昌", "马", "苗", "凤", "花", "方", "俞", "任", "袁", "柳", "酆", "鲍", "史", "唐", "费", "廉", "岑", "薛", "雷", "贺", "倪", "汤", "滕", "殷",
                "罗", "毕", "郝", "邬", "安", "常", "乐", "于", "时", "傅", "皮", "卞", "齐", "康", "伍", "余", "元", "卜", "顾", "孟", "平", "黄", "和",
                "穆", "萧", "尹", "姚", "邵", "湛", "汪", "祁", "毛", "禹", "狄", "米", "贝", "明", "臧", "计", "伏", "成", "戴", "谈", "宋", "茅", "庞", "熊", "纪", "舒",
                "屈", "项", "祝", "董", "梁", "杜", "阮", "蓝", "闵", "席", "季"};
        String girl = "秀娟英华慧巧美娜静淑惠珠翠雅芝玉萍红娥玲芬芳燕彩春菊兰凤洁梅琳素云莲真环雪荣爱妹霞香月莺媛艳瑞凡佳嘉琼勤珍贞莉桂娣叶璧璐娅琦晶妍茜秋珊莎锦黛青倩婷姣婉娴瑾颖露瑶怡婵雁蓓纨仪荷丹蓉眉君琴蕊薇菁梦岚苑婕馨瑗琰韵融园艺咏卿聪澜纯毓悦昭冰爽琬茗羽希宁欣飘育滢馥筠柔竹霭凝晓欢霄枫芸菲寒伊亚宜可姬舒影荔枝思丽 ";
        String boy = "伟刚勇毅俊峰强军平保东文辉力明永健世广志义兴良海山仁波宁贵福生龙元全国胜学祥才发武新利清飞彬富顺信子杰涛昌成康星光天达安岩中茂进林有坚和彪博诚先敬震振壮会思群豪心邦承乐绍功松善厚庆磊民友裕河哲江超浩亮政谦亨奇固之轮翰朗伯宏言若鸣朋斌梁栋维启克伦翔旭鹏泽晨辰士以建家致树炎德行时泰盛雄琛钧冠策腾楠榕风航弘";
        int index = random.nextInt(Surname.length - 1);
        String name = Surname[index]; //获得一个随机的姓氏
        int i = random.nextInt(3);//可以根据这个数设置产生的男女比例
        if (i == 2) {
            int j = random.nextInt(girl.length() - 2);
            if (j % 2 == 0) {
                name = name + girl.substring(j, j + 2);
            } else {
                name = name + girl.substring(j, j + 1);
            }

        } else {
            int j = random.nextInt(girl.length() - 2);
            if (j % 2 == 0) {
                name = name + boy.substring(j, j + 2);
            } else {
                name = name + boy.substring(j, j + 1);
            }

        }

        return name;
    }

}
